home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-09-27 | 8.1 KB | 261 lines | [TEXT/CCL2] |
- ;;; prec-parse.scm -- do precedence parsing of expressions and patterns
- ;;;
- ;;; author : John & Sandra
- ;;; date : 04 Feb 1992
- ;;;
- ;;;
-
-
- ;;; ==================================================================
- ;;; Handling for pp-exp-list
- ;;; ==================================================================
-
- ;;; This function is called during the scope phase after all of the
- ;;; exps in a pp-exp-list have already been walked. Basically, the
- ;;; purpose is to turn the original pp-exp-list into something else.
- ;;; Look for the section cases first and treat them specially.
-
- ;;; Sections are handled by inserting a magic cookie (void) into the
- ;;; list where the `missing' operand of the section would be and then
- ;;; making sure the cookie stays at the top.
-
- ;;; Unary minus needs checking to avoid things like a*-a.
-
- (define (massage-pp-exp-list exps)
- (let* ((first-term (car exps))
- (last-term (car (last exps)))
- (type (cond ((infix-var-or-con? first-term) 'section-l)
- ((infix-var-or-con? last-term) 'section-r)
- (else 'exp)))
- (exps1 (cond ((eq? type 'section-l)
- (cons (make void) exps))
- ((eq? type 'section-r)
- (append exps (list (make void))))
- (else exps)))
- (parsed-exp (parse-pp-list '#f exps1)))
- (if (eq? type 'exp)
- parsed-exp
- (if (or (not (app? parsed-exp))
- (not (app? (app-fn parsed-exp))))
- (begin
- (signal-section-precedence-conflict
- (if (eq? type 'section-l) first-term last-term))
- (make void))
- (let ((rhs (app-arg parsed-exp))
- (op (app-fn (app-fn parsed-exp)))
- (lhs (app-arg (app-fn parsed-exp))))
- (if (eq? type 'section-l)
- (if (void? lhs)
- (make section-l (op op) (exp rhs))
- (begin
- (signal-section-precedence-conflict first-term)
- (make void)))
- (if (void? rhs)
- (make section-r (op op) (exp lhs))
- (begin
- (signal-section-precedence-conflict last-term)
- (make void)))))))))
-
-
- ;;; ==================================================================
- ;;; Handling for pp-pat-list
- ;;; ==================================================================
-
- ;;; In this case, we have to do an explicit walk of the pattern looking
- ;;; at all of its subpatterns.
- ;;; ** This is a crock - the scope walker needs fixing.
-
- (define (massage-pattern pat)
- (cond ((is-type? 'as-pat pat)
- (setf (as-pat-pattern pat) (massage-pattern (as-pat-pattern pat)))
- pat)
- ((is-type? 'irr-pat pat)
- (setf (irr-pat-pattern pat) (massage-pattern (irr-pat-pattern pat)))
- pat)
- ((is-type? 'plus-pat pat)
- (setf (plus-pat-pattern pat) (massage-pattern (plus-pat-pattern pat)))
- pat)
- ((is-type? 'pcon pat)
- (when (eq? (pcon-con pat) *undefined-def*)
- (setf (pcon-con pat) (lookup-toplevel-name (pcon-name pat))))
- (setf (pcon-pats pat) (massage-pattern-list (pcon-pats pat)))
- pat)
- ((is-type? 'list-pat pat)
- (setf (list-pat-pats pat) (massage-pattern-list (list-pat-pats pat)))
- pat)
- ((is-type? 'pp-pat-list pat)
- (parse-pp-list '#t (massage-pattern-list (pp-pat-list-pats pat))))
- ((is-type? 'dynamic-pat pat)
- (setf (dynamic-pat-pat pat) (massage-pattern (dynamic-pat-pat pat)))
- (resolve-signature (dynamic-pat-sig pat))
- pat)
- (else
- pat)))
-
- (define (massage-pattern-list pats)
- (map (function massage-pattern) pats))
-
-
- ;;; ==================================================================
- ;;; Shared support
- ;;; ==================================================================
-
- ;;; This is the main routine.
-
- (define (parse-pp-list pattern? l)
- (mlet (((stack terms) (push-pp-stack '() l)))
- (pp-parse-next-term pattern? stack terms)))
-
- (define (pp-parse-next-term pattern? stack terms)
- (if (null? terms)
- (reduce-complete-stack pattern? stack)
- (let ((stack (reduce-stronger-ops pattern? stack (car terms))))
- (mlet (((stack terms)
- (push-pp-stack (cons (car terms) stack) (cdr terms))))
- (pp-parse-next-term pattern? stack terms)))))
-
- (define (reduce-complete-stack pattern? stack)
- (if (pp-stack-op-empty? stack)
- (car stack)
- (reduce-complete-stack pattern? (reduce-pp-stack pattern? stack))))
-
- (define (reduce-pp-stack pattern? stack)
- (let ((term (car stack))
- (op (cadr stack)))
- (if pattern?
- (cond ((pp-pat-plus? op)
- (let ((lhs (caddr stack)))
- (cond ((or (not (const-pat? term))
- (and (not (var-pat? lhs))
- (not (wildcard-pat? lhs))))
- (signal-plus-precedence-conflict term)
- (cddr stack))
- (else
- (cons (make plus-pat (pattern lhs)
- (k (integer-const-value
- (const-pat-value term))))
- (cdddr stack))))))
- ((pp-pat-negated? op)
- (cond ((const-pat? term)
- (let ((v (const-pat-value term)))
- (if (integer-const? v)
- (setf (integer-const-value v)
- (- (integer-const-value v)))
- (setf (float-const-numerator v)
- (- (float-const-numerator v)))))
- (cons term (cddr stack)))
- (else
- (signal-minus-precedence-conflict term)
- (cons term (cddr stack)))))
- (else
- (setf (pcon-pats op) (list (caddr stack) term))
- (cons op (cdddr stack))))
- (cond ((negate? op)
- (cons (**app (**var/def (core-symbol "negate")) term)
- (cddr stack)))
- (else
- (cons (**app op (caddr stack) term) (cdddr stack)))))))
-
- (define (pp-stack-op-empty? stack)
- (null? (cdr stack)))
-
- (define (top-stack-op stack)
- (cadr stack))
-
- ;;; %%% This does not pick up -5*2 as an error. Too bad!
-
-
- (define (push-pp-stack stack terms)
- (let ((term (car terms)))
- (if (or (negate? term) (pp-pat-negated? term))
- (begin
- (when (and stack (stronger-op? (car stack) term))
- (unary-minus-prec-conflict (car stack)))
- (push-pp-stack (cons term stack) (cdr terms)))
- (values (cons term stack) (cdr terms)))))
-
- (define (reduce-stronger-ops pattern? stack op)
- (cond ((pp-stack-op-empty? stack) stack)
- ((stronger-op? (top-stack-op stack) op)
- (reduce-stronger-ops pattern? (reduce-pp-stack pattern? stack) op))
- (else stack)))
-
- (define (stronger-op? op1 op2)
- (let ((fixity1 (get-op-fixity op1))
- (fixity2 (get-op-fixity op2)))
- (cond ((> (fixity-precedence fixity1) (fixity-precedence fixity2))
- '#t)
- ((< (fixity-precedence fixity1) (fixity-precedence fixity2))
- '#f)
- (else
- (let ((a1 (fixity-associativity fixity1))
- (a2 (fixity-associativity fixity2)))
- (if (eq? a1 a2)
- (cond ((eq? a1 'l)
- '#t)
- ((eq? a1 'r)
- '#f)
- (else
- (signal-precedence-conflict op1 op2)
- '#t))
- (begin
- (signal-precedence-conflict op1 op2)
- '#t))))
- )))
-
- (define (get-op-fixity op)
- (cond ((var-ref? op)
- (pp-get-var-fixity (var-ref-var op)))
- ((con-ref? op)
- (pp-get-con-fixity (con-ref-con op)))
- ((pcon? op)
- (pp-get-con-fixity (pcon-con op)))
- ((or (negate? op) (pp-pat-negated? op))
- (pp-get-var-fixity (core-symbol "-")))
- ((pp-pat-plus? op)
- (pp-get-var-fixity (core-symbol "+")))
- (else
- (error "Bad op ~s in pp-parse." op))))
-
- (define (pp-get-var-fixity def)
- (if (eq? (var-fixity def) '#f)
- default-fixity
- (var-fixity def)))
-
- (define (pp-get-con-fixity def)
- (if (eq? (con-fixity def) '#f)
- default-fixity
- (con-fixity def)))
-
- ;;; Error handlers
-
- (define (signal-section-precedence-conflict op)
- (phase-error 'section-precedence-conflict
- "Operators in section body have lower precedence than section operator ~A."
- op))
-
- (define (signal-precedence-conflict op1 op2)
- (phase-error 'precedence-conflict
- "The operators ~s and ~s appear consecutively, but they have the same~%~
- precedence and are not either both left or both right associative.~%~
- You must add parentheses to avoid a precedence conflict."
- op1 op2))
-
- (define (signal-plus-precedence-conflict term)
- (phase-error 'plus-precedence-conflict
- "You need to put parentheses around the plus-pattern ~a~%~
- to avoid a precedence conflict."
- term))
-
- (define (signal-minus-precedence-conflict arg)
- (phase-error 'minus-precedence-conflict
- "You need to put parentheses around the negative literal ~a~%~
- to avoid a precedence conflict."
- arg))
-
- (define (unary-minus-prec-conflict arg)
- (recoverable-error 'minus-precedence-conflict
- "Operator ~A too strong for unary minus; extra parens are required~%"
- arg))
-
-